﻿// --------------------------------
// <copyright file="ListView.cs" company="Faculty of Information Technology, Czech Technical University in Prague">
//     This document is shared by Microsoft Public License (MS-PL)
//     For further details please see http://msdn.microsoft.com/en-us/library/ff648068.aspx or license.txt.
// </copyright>
// <author>Lukáš Molnár</author>

// <email>molnaluk@fit.cvut.cz</email>

// <date>9. 11. 2011 22:22:38</date>

// <summary>
//
// </summary>
// --------------------------------

#if WINDOWS

using System.ComponentModel;
using FITClub.TextureMenu.Configuration;
using System.Drawing.Design;
using FITClub.Episode1.Levels;

#endif

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;

namespace FITClub.TextureMenu
{
#if WINDOWS

    [System.Serializable]
#endif
    public class ListView : AMenuItemList<string>
    {
        [XmlElement]
        public int ItemHeight { get; set; }

#if WINDOWS

        [Category("Colors")]
        [Editor(typeof(ColorEditor), typeof(UITypeEditor))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlElement]
        public Color BackgroundColor { get; set; }

#if WINDOWS

        [Category("Path")]
        [Editor(typeof(ContentPathEditor), typeof(UITypeEditor))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlAttribute]
        public string FontPath { get; set; }

        protected Rectangle contentBounds;
#if WINDOWS
        [System.NonSerialized]
#endif
        private Texture2D backgroundTexture;
#if WINDOWS
        [System.NonSerialized]
#endif
        private Texture2D selection;
        private int firstVisible;
        private int visibleCount;
#if WINDOWS
        [System.NonSerialized]
#endif
        private SpriteFont font;

#if WINDOWS_PHONE == flase

        public override void Resized(double ratioX, double ratioY)
        {
            base.Resized(ratioX, ratioY);
            ItemHeight = (int)(ItemHeight * ratioY);
            ResetBounds();
        }

#endif

        private void ResetBounds()
        {
            contentBounds = new Rectangle(this.Bounds.X + offset.X, this.Bounds.Y + offset.Y, this.Bounds.Width - 2 * offset.X, this.Bounds.Height - 2 * offset.Y);
            visibleCount = this.contentBounds.Height / this.ItemHeight;
        }

        public override void Move(Point delta)
        {
            base.Move(delta);
            this.ResetBounds();
        }

        public override void Update(GameTime gt)
        {
            for (int i = firstVisible; i < this.firstVisible + this.visibleCount && i < this.Options.Count; i++)
            {
                Rectangle itembounds = new Rectangle(this.Bounds.X, this.Bounds.Y + (i - firstVisible) * ItemHeight, this.Bounds.Width, this.ItemHeight);
                if (MenuManager.Current.MouseUpTest(itembounds) || MenuManager.Current.TapTest(itembounds))
                {
                    this.TraverseItems(i - this.SelectedIndex);
                    return;
                }
            }
#if WINDOWS_PHONE

            if (MenuManager.Current.ActualGestureSamples.Count > 0)
            {
                var drag = (from itm in MenuManager.Current.ActualGestureSamples
                            where itm.GestureType == GestureType.VerticalDrag
                            select itm.Delta);
                Vector2 totalDelta = Vector2.Zero;
                foreach (var item in drag)
                {
                    totalDelta += item;
                }
                int move = (int)totalDelta.Y / this.ItemHeight;
                if (move != null)
                {
                    this.TraverseItems(move);
                    return;
                }
            }
#endif
            base.Update(gt);
        }

        public override void Draw(SpriteBatch spriteBatch, Color tint)
        {
            if (this.IsSelected)
            {
                MenuHelper.DrawBorder(spriteBatch, this.Bounds, Owner.SelectedItemBackground, 5);
            }

            spriteBatch.Draw(backgroundTexture, this.Bounds, tint);
            Vector2 p = new Vector2(this.contentBounds.X, this.contentBounds.Y);
            for (int i = firstVisible; i < this.firstVisible + this.visibleCount && i < this.Options.Count; i++)
            {
                if (i == SelectedIndex)
                {
                    spriteBatch.Draw(this.selection, new Rectangle((int)p.X, (int)p.Y, this.contentBounds.Width, ItemHeight), tint);
                }
#if WINDOWS_PHONE
                spriteBatch.DrawString(font, this.Options[i], p, this.TextColor);
#else
                spriteBatch.DrawString(font, this.Options[i], p, this.TextColor, 0, Vector2.Zero, (float)MenuManager.ScaleY, SpriteEffects.None, 0); //// vycentrovat
#endif
                p.Y += this.ItemHeight;
            }
        }

        public override void LoadContent(ContentManager loader)
        {
            if (ContentLoaded == false)
            {
                this.ResetBounds();
                ContentLoaded = true;
                if (backgroundTexture == null)
                {
                    backgroundTexture = MenuHelper.CreateFillTexture(this.BackgroundColor);
                    selection = MenuHelper.CreateFillTexture(this.SelectionColor);
                }
                this.font = MenuHelper.LoadFontOrDefault(loader, this.FontPath);
            }
        }

        public override void Dispose()
        {
            if (ContentLoaded)
            {
                if (this.selection != null)
                {
                    this.selection.Dispose();
                    this.backgroundTexture.Dispose();
                    this.selection = null;
                    this.backgroundTexture = null;
                }
                ContentLoaded = false;
            }
        }

        public override void TraverseItems(int selectionMove)
        {
            if (this.Options == null || this.Options.Count == 0) return;

            if (selectionMove > 0)
            {
                if (selectionMove + SelectedIndex < this.Options.Count)
                {
                    SelectedIndex += selectionMove;
                    if (SelectedIndex > firstVisible + visibleCount - 1)
                    {
                        firstVisible += selectionMove;
                    }
                }
                else
                {
                    this.SelectedIndex = this.Options.Count - 1;
                    firstVisible = (this.Options.Count - visibleCount >= 0) ? this.Options.Count - visibleCount : 0;
                }
                this.SoundAndAction();
            }

            if (selectionMove < 0)
            {
                if (selectionMove + SelectedIndex >= 0)
                {
                    {
                        SelectedIndex += selectionMove;
                        if (SelectedIndex < firstVisible)
                        {
                            firstVisible += selectionMove;
                        }
                    }
                }
                else
                {
                    SelectedIndex = 0;
                    firstVisible = 0;
                }
                SoundAndAction();
            }
        }

        private void SoundAndAction()
        {
            if (this.SelectionSound != null)
            {
                this.SelectionSound.Play();
            }
            if (this.Action != null && this.IgnoreParam == false && this.Options.Count > 0)
            {
                this.Action.Param = this.Options[SelectedIndex];
            }
        }
    }
}